﻿using System.Collections.Generic;
using UnityEngine;
using XLua;

namespace Mga
{
	public enum InjectionType
	{
		String = 0,
		Int = 1,
		Float = 2,
		Boolean = 3,
		Object = 10,
		GameObject = 11,
		Transform = 12,
		Collider = 13,
		Behaviour = 14,
		Renderer = 15,
		Curve = 21,
		List = 98,
		Dict = 99
	}

	[System.Serializable]
	public class Injection
	{
		[SerializeField]
		protected string m_Name;
		public string Name
		{
			get
			{
				return m_Name;
			}
			set
			{
				m_Name = value;
			}
		}

		[SerializeField]
		protected InjectionType m_Type;
		public InjectionType Type
		{
			get
			{
				return m_Type;
			}
			set
			{
				if (value != m_Type)
				{
					object v = GetValue();
					m_Type = value;
					ResetValue();
					SetValue(v);
				}
			}
		}

		[SerializeField]
		protected string m_StringValue;
		[SerializeField]
		protected int m_IntValue;
		[SerializeField]
		protected float m_FloatValue;
		[SerializeField]
		protected bool m_BooleanValue;
		[SerializeField]
		protected Object m_ObjectValue;
		[SerializeField]
		protected AnimationCurve m_CurveValue;
		public object Value
		{
			get
			{
				return GetValue();
			}
			set
			{
				ResetValue();
				SetValue(value);
			}
		}

		protected virtual object GetValue()
		{
			switch (Type)
			{
				case InjectionType.String:
					return m_StringValue;
				case InjectionType.Int:
					return m_IntValue;
				case InjectionType.Float:
					return m_FloatValue;
				case InjectionType.Boolean:
					return m_BooleanValue;
				case InjectionType.Object:
				case InjectionType.GameObject:
				case InjectionType.Transform:
				case InjectionType.Collider:
				case InjectionType.Behaviour:
				case InjectionType.Renderer:
					return m_ObjectValue;
				case InjectionType.Curve:
					return m_CurveValue;
			}
			return null;
		}

		protected virtual void SetValue(object value)
		{
			switch (Type)
			{
				case InjectionType.String:
					m_StringValue = (value ?? "").ToString();
					break;
				case InjectionType.Int:
					if (value is int)
					{
						m_IntValue = (int) value;
					}
					break;
				case InjectionType.Float:
					if (value is float)
					{
						m_FloatValue = (float) value;
					}
					break;
				case InjectionType.Boolean:
					if (value is bool)
					{
						m_BooleanValue = (bool) value;
					}
					break;
				case InjectionType.Object:
				case InjectionType.GameObject:
				case InjectionType.Transform:
				case InjectionType.Collider:
				case InjectionType.Behaviour:
				case InjectionType.Renderer:
					if (value is Object)
					{
						m_ObjectValue = value as Object;
					}
					break;
				case InjectionType.Curve:
					if (value is AnimationCurve)
					{
						m_CurveValue = value as AnimationCurve;
					}
					break;
			}
		}

		protected virtual void ResetValue()
		{
			m_StringValue = null;
			m_IntValue = 0;
			m_FloatValue = 0;
			m_BooleanValue = false;
			m_ObjectValue = null;
			m_CurveValue = null;
		}

		public static LuaTable ToValueTable(InjectionType type, object value)
		{
			if (value is List<Injection4>)
			{
				return ToValueTable(type, value as List<Injection4>);
			}
			else if (value is List<Injection3>)
			{
				return ToValueTable(type, value as List<Injection3>);
			}
			else if (value is List<Injection2>)
			{
				return ToValueTable(type, value as List<Injection2>);
			}
			else if (value is List<Injection1>)
			{
				return ToValueTable(type, value as List<Injection1>);
			}
			else if (value is List<Injection>)
			{
				return ToValueTable(type, value as List<Injection>);
			}
			return null;
		}

		private static LuaTable ToValueTable<T>(InjectionType type, List<T> array) where T : Injection
		{
			LuaTable table = XLuaComponent.LuaEnv.NewTable();
			for (int index = 0; index < array.Count; index++)
			{
				T injection = array[index];
				object value = injection.Value;
				if (injection.Type == InjectionType.List || injection.Type == InjectionType.Dict)
				{
					value = ToValueTable(injection.Type, injection.Value);
				}
				if (type == InjectionType.List)
				{
					table.Set(index + 1, value);
				}
				else
				{
					table.Set(injection.Name, value);
				}
			}
			return table;
		}
	}

	[System.Serializable]
	public class Injection<T> : Injection
	{
		[SerializeField]
		private List<T> m_ListOrDictValue;
		protected override object GetValue()
		{
			if (Type == InjectionType.List || Type == InjectionType.Dict)
			{
				return m_ListOrDictValue;
			}
			return base.GetValue();
		}
		protected override void SetValue(object value)
		{
			if (Type == InjectionType.List || Type == InjectionType.Dict)
			{
				if (value is List<T>)
				{
					m_ListOrDictValue = value as List<T>;
				}
			}
			else
			{
				base.SetValue(value);
			}
		}
		protected override void ResetValue()
		{
			base.ResetValue();
			m_ListOrDictValue = null;
		}
	}

	[System.Serializable]
	public class Injection1 : Injection<Injection>
	{
	}

	[System.Serializable]
	public class Injection2 : Injection<Injection1>
	{
	}

	[System.Serializable]
	public class Injection3 : Injection<Injection2>
	{
	}

	[System.Serializable]
	public class Injection4 : Injection<Injection3>
	{
	}
}
